import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;

import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.script.Calculations;
import com.speljohan.rsbot.script.Constants;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.Skills;
import com.speljohan.rsbot.script.wrappers.RSInterface;
import com.speljohan.rsbot.script.wrappers.RSItemTile;
import com.speljohan.rsbot.script.wrappers.RSNPC;
import com.speljohan.rsbot.script.wrappers.RSObject;
import com.speljohan.rsbot.script.wrappers.RSTile;

public class XiOutpostWillowsiX extends Script implements PaintListener {

	public static final int WOODCUTTING_STAT = Skills
			.getStatIndex("Woodcutting");

	public boolean FullInv = false;

	public int DepoBox = 20228;
	private final int[] nestIds = { 5075, 5074, 5073, 5072, 5071, 5070, 7413 };
	public static int[] willowTrees = { 1308, 5551, 5552, 5553, 8481, 8482,
			8483, 8484, 8485, 8486, 8487, 8488 };
	public static int willowLogs = 1519;
	public int logcount;
	int startLevel = 0;
	int startXP = 0;
	public int logsBanked = 0;
	int State = 0;
	int Door = 20195;
	int nestsFound = 0;
	int randomRun = random(20, 65);
	int checkTime;
	long startTime;
	RSTile RANDOMIZE_TILE = new RSTile(2520, 3580).randomizeTile(2, 2);
	long lastCheck;
	RSTile PATH[] = { new RSTile(2529, 3571), new RSTile(2536, 3573) };

	long startTime1 = System.currentTimeMillis();

	int antiBan() {
		final int p = Math.round(random(1, 11));
		switch (p) {
		case 1:
			wait(random(1000, 1500));
			return random(500, 750);

		case 2:
			final int x = random(0, 750);
			final int y = random(0, 500);
			moveMouse(0, 0, x, y);
			return random(500, 1000);

		case 3:
			// Is the current tab the inventory?
			if (getCurrentTab() != Constants.TAB_INVENTORY) {
				// No, so switch to the inventory tab.
				openTab(Constants.TAB_INVENTORY);
				return random(500, 750);
			} else {
				// No, so return
				return random(500, 750);
			}

		case 4:
			final int x1 = random(0, 750);
			final int y1 = random(0, 500);
			moveMouse(0, 0, x1, y1);
			return random(1000, 1500);

		case 5:
			if (random(1, 8) == 2) {
				int angle = getCameraAngle() + random(-90, 90);
				if (angle < 0) {
					angle = 0;
				}
				if (angle > 359) {
					angle = 0;
				}

				setCameraRotation(angle);
			}
			return random(500, 750);

		case 6:
			final int x2 = random(0, 750);
			final int y2 = random(0, 500);
			moveMouse(0, 0, x2, y2);
			return random(1000, 1500);
		}
		return random(500, 700);
	}

	public boolean atDepositInventoryItem(final int itemID, final String txt) {
		if (!interfaceExists(Constants.INTERFACE_DEPOSITBOX) || !isLoggedIn()) {
			return false;
		}
		for (int off = 0; off < getInventoryArray().length; off++) {
			if (getInventoryArray()[off] == itemID) {
				clickMouse(getDepositInventoryItemPoint(off), 3, 3, false);
				wait(random(200, 300));
				return atMenu(txt);
			}
		}
		return false;
	}

	public boolean busy() {
		if (getMyPlayer().isInCombat()) {
			runAway();
			return true;
		}
		if (getMyPlayer().getAnimation() == 879
				|| getMyPlayer().getAnimation() == 875
				|| getMyPlayer().getAnimation() == 867
				|| getMyPlayer().getAnimation() == 2846) {
			return true;
		}
		if (getMyPlayer().isMoving()) {
			return true;
		}

		return false;
	}

	public int chop() {
		final RSObject Tree = findClosestObjectInRange(
				XiOutpostWillowsiX.willowTrees, 8);
		setCameraAltitude(true);
		setCameraRotation(170);
		try {
			// log.info("Tree Location:" + Tree.getLocation().getX() +
			// " - " + Tree.getLocation().getY());
			// log.info("My Location:" +
			// getMyPlayer().getLocation().getX() + " - " +
			// getMyPlayer().getLocation().getY());
			// atObject(Tree, "Chop down");

			int treeX, treeY;
			treeX = (int) Calculations.tileToScreen(Tree.getLocation()).getX();
			treeY = (int) Calculations.tileToScreen(Tree.getLocation()).getY();
			treeX = treeX + random(10, 20);
			treeY = treeY - random(5, 10);
			final Point t = new Point(treeX, treeY);
			moveMouse(t);
			clickMouse(true);
			State = 0;

		} catch (final NullPointerException NPE) {
			NPE.printStackTrace();
		} catch (final Exception ex) {
			ex.printStackTrace();
		}
		return random(1000, 2000);
	}

	public boolean depositAllDepositBoxExcept(final int... items) {
		int inventoryCount = getInventoryCount();
		for (int off = 0; off < getInventoryArray().length; off++) {
			if (getInventoryArray()[off] == -1) {
				continue;
			}
			boolean skip = false;
			for (final int item : items) {
				if (getInventoryArray()[off] == item) {
					skip = true;
					break;
				}
			}
			if (skip) {
				continue;
			}

			for (int tries = 0; tries < 5; tries++) {
				atDepositInventoryItem(getInventoryArray()[off], "Deposit-All");
				wait(random(1000, 1500));
				if (getInventoryCount() < inventoryCount) {
					break;
				}
			}
			if (getInventoryCount() >= inventoryCount) {
				// equally, otherwise
				// something realy weird
				// happend :P
				return false;
			}
			inventoryCount = getInventoryCount();
		}
		return true;
	}

	public boolean ent() {
		final RSNPC ent = getNearestNPCByName("Willow");
		if (distanceTo(ent) <= 2) {
			log("Found Ent changing Tree");
			return true;
		}
		return false;
	}

	public RSObject findClosestObjectInRange(final int IDs[], final int range) {
		try {
			int myX, myY, minX, minY, maxX, maxY, objX, objY;
			RSObject temp;
			RSObject output = null;
			myX = getMyPlayer().getLocation().getX();
			myY = getMyPlayer().getLocation().getY();
			minX = range * -1;
			minY = range * -1;
			maxX = range;
			maxY = range;
			for (int x = minX; x < maxX; x++) {
				for (int y = minY; y < maxY; y++) {
					objX = myX + x;
					objY = myY + y;
					temp = getObjectAt(objX, objY);
					if (temp == null) {
						continue;
					}
					for (final int ID : IDs) {
						if (temp.getID() == ID) {
							if (output == null) {
								output = temp;
							} else {
								if (distanceTo(temp.getLocation()) < distanceTo(output
										.getLocation())) {
									output = temp;
								}
							}
						}
					}

				}
			}
			return output;
		}

		catch (final Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public String getAuthor() {
		return "Zzscorp";
	}

	public Point getDepositInventoryItemPoint(final int invIndex) {
		final int col = invIndex % 7;
		final int row = invIndex / 7;
		final int x = 121 + col * 48;
		final int y = 85 + row * 50;
		return new Point(x, y);
	}

	@Override
	public String getName() {
		return "XiOutpostWillows";
	}

	@Override
	public String getScriptCategory() {
		return "Woodcutting";
	}

	@Override
	public String getScriptDescription() {
		return "<html>\n" + "<head></head>\n" + "<body>\n" + "<center>"
				+ "<h2>" + getName() + "</h2>" + "</center>\n"
				+ "<b>Author:</b> " + getAuthor() + "<br />"
				+ "<b>Version:</b> " + getVersion() + "<br />" +

				"<b>Features:</b>" + "<ul><li>Built in Anti-ban</li></ul>"
				+ "<ul><li>Flawless nest picking!</li></ul>"
				+ "<ul><li>Flawless Banking woot!</li></ul>"
				+ "<ul><li>Remember- zzscorp sees all!</li></ul>" +

				"</body>\n" + "</html>";
	}

	@Override
	public double getVersion() {
		return 3.6;
	}

	@Override
	public int loop() {
		if (!isRunning() && getEnergy() > random(40, 60)) {
			setRun(true);
			wait(random(560, 930));
		}
		// log("State: " + State);
		try {
			switch (State) {
			case 0:
				if (ent()) {
					walkTileMM(RANDOMIZE_TILE);
					return chop();
				}
				if (busy()) {
					final RSItemTile nest = getGroundItemByID(nestIds);
					if (nest != null) {
						log("Found nest");
						atTile(nest, "Take");
						nestsFound++;
					}
					antiBan();
					return random(800, 1000);
				}

				if (distanceTo(new RSTile(2536, 3573)) < 3) {
					State = 2;
					return random(300, 1000);
				}

				if (isInventoryFull()) {
					State = 1;
					return random(300, 1500);
				}

				if (distanceTo(RANDOMIZE_TILE) > 7) {
					State = 3;
					return random(500, 1000);
				}

				return chop();
			case 1:
				return walkToBank();
			case 2:
				final RSObject depositBox = findObject(DepoBox);
				if (findObject(DepoBox) != null
						&& distanceTo(depositBox.getLocation()) > 5) {
					walkPathMM(PATH, 14);
					return random(300, 1000);
				}
				if (findObject(DepoBox) != null
						&& !RSInterface.getInterface(
								Constants.INTERFACE_DEPOSITBOX).isValid()) {
					atObject(findObject(DepoBox), "Deposit");
					return random(500, 1250);
				}
				if (RSInterface.getInterface(Constants.INTERFACE_DEPOSITBOX)
						.isValid()) {
					logsBanked += getInventoryCount(XiOutpostWillowsiX.willowLogs);
					depositAllDepositBoxExcept(995, 1349, 1351, 1353, 1355,
							1357, 1359, 1361, 6739);
					State++;
				}
				if (inventoryContains(XiOutpostWillowsiX.willowLogs)) { // if
					// your
					// full.
					return random(750, 1250);
				}
			case 3:
				return walkToCuttingSpot();

			}
		} catch (final Exception e) {
			e.printStackTrace();
		}
		return random(500, 1000);

	}

	@Override
	public void onFinish() {
		Bot.getEventManager().removeListener(PaintListener.class, this);
	}

	public void onRepaint(final Graphics g) {
		if (isLoggedIn()) {
			final int Xbox = 6;
			final int Ybox = 10;
			final int Xprint = Xbox + 5;
			final int Yprint = Ybox + 15;
			long millis = System.currentTimeMillis() - startTime1;
			final long hours = millis / (1000 * 60 * 60);
			millis -= hours * 1000 * 60 * 60;
			final long minutes = millis / (1000 * 60);
			millis -= minutes * 1000 * 60;
			final long seconds = millis / 1000;
			final int XPChange = skills.getCurrentSkillExp(8) - startXP;
			final int LevelChange = skills.getCurrentSkillLevel(8) - startLevel;
			if ((minutes > 0 || hours > 0 || seconds > 0) && XPChange > 0) {
			}
			g.setColor(Color.black);
			g.drawRoundRect(Xbox, Ybox, 270 - 1, 95 - 1, 20, 20);
			g.setColor(new Color(255, 255, 255, 100));
			g.fillRoundRect(Xbox + 1, Ybox + 1, 270 - 2, 95 - 2, 20, 20);

			g.setColor(Color.yellow);
			g.drawString("Banked " + Integer.toString(logsBanked)
					+ " Willow Logs", Xprint + 2, Yprint + 2);
			g.drawString("Runtime: " + hours + " hours " + minutes
					+ " minutes " + seconds + " seconds.", Xprint + 2,
					Yprint + 17);
			g.drawString("Current: " + skills.getCurrentSkillLevel(8)
					+ " levels and " + skills.getCurrentSkillExp(8) + " exp.",
					Xprint + 2, Yprint + 32);
			g.drawString("Gained: " + LevelChange + " levels and " + XPChange
					+ " exp.", Xprint + 2, Yprint + 47);
			g.drawString("Found: " + nestsFound + " nests", Xprint + 2,
					Yprint + 62);

			g.drawString(skills.getXPToNextLevel(8)
					+ " XP to next level, we are "
					+ skills.getPercentToNextLevel(8) + "% to next level.",
					Xprint + 2, Yprint + 77);

			g.setColor(Color.black);
			g.drawString("Banked " + Integer.toString(logsBanked)
					+ " Willow Logs", Xprint, Yprint);
			g.drawString("Runtime: " + hours + " hours " + minutes
					+ " minutes " + seconds + " seconds.", Xprint, Yprint + 15);
			g.drawString("Current: " + skills.getCurrentSkillLevel(8)
					+ " levels and " + skills.getCurrentSkillExp(8) + " exp.",
					Xprint, Yprint + 30);
			g.drawString("Gained: " + LevelChange + " levels and " + XPChange
					+ " exp.", Xprint, Yprint + 45);
			g
					.drawString("Found: " + nestsFound + " nests", Xprint,
							Yprint + 60);

			g.drawString(skills.getXPToNextLevel(8)
					+ " XP to next level, we are "
					+ skills.getPercentToNextLevel(8) + "% to next level.",
					Xprint, Yprint + 75);

		}
	}

	@Override
	public boolean onStart(final String[] s) {
		logcount = 0;
		logsBanked = 0;
		startTime1 = System.currentTimeMillis();
		if (isLoggedIn()) {
			startLevel = skills.getCurrentSkillLevel(8);
			startXP = skills.getCurrentSkillExp(8);
		}
		log("Started Zzscorp's Outpost Chopper");
		return true;
	}

	public boolean runAway() {
		RSTile a, b;
		a = getMyPlayer().getLocation();
		b = new RSTile(a.getX() + 10, a.getY() + 10);
		walkTileMM(b);
		wait(random(10000, 20000));
		walkTileMM(a);
		return true;
	}

	public int walkToBank() {
		if (getMyPlayer().isMoving()) {
			return random(1500, 2000);
		}
		if (distanceTo(new RSTile(2535 + random(-1, 1), 3574 + random(-1, 1))) < 7) {
			wait(random(750, 1500));
			State++;
			return random(400, 1000);

		} else if (distanceTo(findObject(Door)) <= 30) {
			walkTileMM(new RSTile(2520 + random(-1, 2), 3571 + random(-1, 2)));
			wait(random(4000, 4500));
			setCameraRotation(271);
			atDoor(findObject(Door), "e", "Open");
			wait(random(1500, 2000));
		} else {

			walkPathMM(PATH, 14);
			wait(random(400, 1000));
		}
		return random(500, 1500);
	}

	public int walkToCuttingSpot() {
		if (getMyPlayer().isMoving()) {
			return random(1500, 2000);
		}
		if (distanceTo(new RSTile(2520 + random(-1, 2), 3580 + random(-1, 2))) < 7) {
			wait(random(750, 1500));
			State = 0;
			return random(750, 1500);

		} else if (distanceTo(findObject(Door)) <= 30) {
			walkTileMM(new RSTile(2523 + random(-1, 2), 3571 + random(-1, 1)));
			wait(random(3000, 4000));
			setCameraRotation(271);
			atDoor(findObject(Door), "e", "Open");
			wait(random(1500, 2000));
		} else {
			walkTileMM(new RSTile(2523 + random(-1, 2), 3571 + random(-1, 1)));
			wait(random(750, 1250));
			walkTileMM(new RSTile(2520 + random(-1, 2), 3580 + random(-1, 2)));
			wait(random(750, 1500));
		}
		return random(500, 1500);
	}
}